/*
 * HackSQL
 * Copyright (C) 2008-2009
 *
 * Authors: Henrique Montenegro Decaria
 *
 * This program is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>

#include "hs_parser_common.h"
#include "hs_sql_parser.h"

#define HACKSQL_PORT	  "4225"
#define HACKSQL_BACKLOG   20
#define HACKSQL_BUFFER	255

int main(int argc, char **argv)
{
	int my_sock, their_sock;
	int received;
	
	/*
		struct addrinfo {
			   int			  ai_flags;
			   int			  ai_family;
			   int			  ai_socktype;
			   int			  ai_protocol;
			   size_t		   ai_addrlen;
			   struct sockaddr *ai_addr;
			   char			*ai_canonname;
			   struct addrinfo *ai_next;
		};
	*/
	struct addrinfo *local;
	struct addrinfo info;
	
	struct sockaddr_storage remote;
	socklen_t remotelen;
	
	char buf[HACKSQL_BUFFER+1];
	
	memset(&info, 0, sizeof(info));
	info.ai_family = AF_INET; /* For now, only IPV4 */
	info.ai_socktype = SOCK_STREAM;
	info.ai_flags = AI_PASSIVE;
	
	if( getaddrinfo(NULL, HACKSQL_PORT, &info, &local) != 0 ) {
		printf("Error on getaddrinfo\n");
		return -1;
	}
	
	my_sock = socket(local->ai_family, local->ai_socktype, local->ai_protocol);
	
	if( my_sock < 0 ) {
		printf("Error creating the socket\n");
		return -1;
	}
	
	bind(my_sock, local->ai_addr, local->ai_addrlen);
	listen(my_sock, HACKSQL_BACKLOG);
	
	while(1) {
		remotelen = sizeof(remote);
		their_sock = accept(my_sock, (struct sockaddr *)&remote, &remotelen);
		
		if (their_sock == -1) {
			perror("Error accepting connection\n");
			continue;
		}
		
		if(!fork()) { // Child process goes in
			// I am the child, daddy wont come here :)
			close(my_sock);
			
			while(1) {
				received = recv(their_sock, buf, HACKSQL_BUFFER, 0);
				buf[received] = '\0';
			
				/* Here we pass buf to the parser. Note that buf might
				 * not contain the whole query. A logic needs to be added
				 * to determine when the client finished sending the query
				 * so we can pass it to the parser */
			
				printf("Received data %s: their_sock is %d; received is %d\n", buf, their_sock,received);
				
				if( strcmp(buf,"close_hs_connection") == 0 ) {
					break;
				} else {
					printf("Parsing query %s\n",buf);
					hs_parser_query(buf);
				}
				
				if (received == 0)
					break;
			}
			
			/* Child process is finished with its work, so exit */
			close(their_sock);
			return 0;
		}
		
	}
	
	freeaddrinfo(local);
	
	close(my_sock);
	
}
